package com.etlmaster.executor.steps.log;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileType;

import com.etlmaster.executor.Step;
import com.etlmaster.executor.StepMeta;
import com.etlmaster.executor.annotation.StepInstruction;
import com.etlmaster.executor.steps.log.ThreadMessages.Message;
import com.etlmaster.executor.utils.DpVfsUtils;
import com.etlmaster.executor.utils.Regex;
import com.etlmaster.executor.utils.StepState;
import com.etlmaster.jdbc.JdbcTemplate;

/**
 * 解析日志文件，提取错误行
 * @author Larry
 * @copyright Larry@etlMaster
 * @since 2017-09-10
 */
@StepInstruction("logAnalyze")
public class LogAnalyzeStep extends Step{

	private LogAnalyzeStepMeta meta;
	public LogAnalyzeStep(StepMeta meta) {
		super(meta);
		this.meta=(LogAnalyzeStepMeta) meta;
	}

	@Override
	protected int handle() {
			FileObject fileObject = DpVfsUtils.getInstance().resolveFile(
					meta.getFilePath());
			Map<String,ThreadMessages> threads=new HashMap<String,ThreadMessages>();
			List<Message> errorthreads=new ArrayList<Message>();

			try {
				if (!fileObject.exists()) {
					meta.log("ERROR","文件不存在，{}", meta.getFilePath());
					return StepState.RUNNING_FAILED;
				}

				if (fileObject.getType() == FileType.FILE) {
					meta.log("INFO","开始解析文件:{}",fileObject.getName().getURI());
					InputStream in = fileObject.getContent().getInputStream();

					try {
						InputStreamReader reader=new InputStreamReader(in);
						BufferedReader br=new BufferedReader(reader);
						String lastThreadName="";
						while(br.ready()){
							String line=br.readLine();
							String threadName=Regex.validation(line, meta.getRegex(), 3);
							ThreadMessages threadMsg;
							if(threadName.equals("null")){
								threadName=lastThreadName;
								threadMsg=threads.get(threadName);
								if(threadMsg!=null)
									threadMsg.appendMessage(line);
								
							}else{
								lastThreadName=threadName;
								threadMsg=threads.get(threadName);
								if(threadMsg==null){
									threadMsg=new ThreadMessages(meta.getSize());
								}
								String []msgs=Regex.validations(line, meta.getRegex());
								Message msg=threadMsg.addMessage(msgs[0], msgs[1],msgs[2], msgs[3],msgs[4]);
								if(msg.hasError()){
									for(Message entity:threadMsg.getMessages()){
										errorthreads.add(entity);
									}
								}
								
							}
							
							threads.put(threadName, threadMsg);
						}

						if(errorthreads.size()>0)
						{
							meta.log("INFO","文件{}解析完成，提交到数据库",fileObject.getName().getURI());
							updateToTable(fileObject.getName().getBaseName().split("\\.")[0],errorthreads);
						}else{
							meta.log("INFO","文件{}未发现错误日志",fileObject.getName().getURI());

						}

					} catch (IOException e) {
						meta.log("ERROR","IO异常：{}",e.getMessage());
						e.printStackTrace();
					} finally {
						try {
							in.close();
						} catch (IOException e) {
							meta.log("ERROR","关闭输入流异常：{}",e.getMessage());
							return StepState.RUNNING_FAILED;
						}
						DpVfsUtils.getInstance().closeFileObject(fileObject);
					}
				}
			} catch (FileSystemException e) {
				meta.log("ERROR","文件异常：{}",e.getMessage());
				return StepState.RUNNING_FAILED;
			} catch (Exception e) {
				meta.log("ERROR","异常：{}",e.getMessage());
				e.printStackTrace();
				return StepState.RUNNING_FAILED;
			}
		return 0;
	}

	private void updateToTable(String fileName,List<Message> errorthreads){
		String sql="insert into error_log values(?,?,?,?,?,'"+fileName+"')";
		JdbcTemplate jdbcTeample=new JdbcTemplate();
		List<Object []> errorMsgs=new ArrayList<Object[]>();
		for(Message entity:errorthreads){
			Object []msgs=new String[5];
			msgs[0]=entity.getDate();
			msgs[1]=entity.getHour();
			msgs[2]=entity.getLevel();
			msgs[3]=entity.getMessage();
			msgs[4]=entity.getThreadName();
			errorMsgs.add(msgs);
		}
		jdbcTeample.batchUpdate(sql, errorMsgs);
	}
	@Override
	public boolean stop() {
		// TODO Auto-generated method stub
		return false;
	}

}
